package com.haide.channel.pro.util.seq;


import com.haide.channel.pro.constant.DateFormatDict;
import com.haide.channel.pro.constant.NumberDict;
import com.haide.channel.pro.constant.SymbolDict;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 生成id工具类
 * <p>
 * 1.
 * </p>
 *
 * @author : wukong
 * @version : 1.0.0
 * @date : 2018/6/27
 */
@Slf4j
public final class CgwGenerateIdUtil {
    /**
     * 原子锁
     */
    private static final AtomicInteger LOCK = new AtomicInteger(0);
    /**
     * 生成UUID的字符集
     */
    private static final String[] CHARS = new String[]{"a", "b", "c", "d", "e", "f",
            "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
            "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z"};
    /**
     * 序列集合
     */
    private static Set<String> sequenceSet = new ConcurrentSkipListSet<>();

    private CgwGenerateIdUtil() {

    }

    /**
     * 生成UUID
     *
     * @return String
     */
    public static String generateShortUuid() {
        final int num = 0x3E;
        final int end = 16;
        final int eight = 8;
        final int four = 4;
        log.info("生成uuid开始...");
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", SymbolDict.EMPTY);
        for (int i = 0; i < eight; i++) {
            String str = uuid.substring(i * four, i * four + four);
            int x = Integer.parseInt(str, end);
            shortBuffer.append(CHARS[x % num]);
        }
        log.info("uuid：{}", shortBuffer.toString());
        return shortBuffer.toString();

    }

    public static void main(String[] args) {
        System.out.println();
    }

    public static String getSeq() {
        return CgwGenerateIdUtil.generateSequence(DateFormatDict.YYMMDDHHMMSS, 7);
    }

    /**
     * 生成序列
     *
     * @param length 长度
     * @return string
     */
    public static String generateSequence(double length) {
        String result = SymbolDict.EMPTY;
        try {
            if (LOCK.get() == 0) {
                LOCK.incrementAndGet();
                boolean flag = true;
                DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(DateFormatDict.SSSS);
                result = getSeq(length, flag, dateTimeFormatter);
            }
        } catch (Exception e) {
            log.error("生成序列号异常", e);
        } finally {
            LOCK.set(0);
        }
        return result;
    }

    /**
     * 根据时间生成序列
     *
     * @param dateFormat 日期格式
     * @param length     长度
     * @return string
     */
    public static String generateSequence(String dateFormat, double length) {
        String result = SymbolDict.EMPTY;
        try {
            if (LOCK.get() == 0) {
                LOCK.incrementAndGet();
                boolean flag = true;
                DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(dateFormat);
                result = getSeq(length, flag, dateTimeFormatter);
            }
        } catch (Exception e) {
            log.error("生成序列号异常", e);
        } finally {
            LOCK.set(0);
        }
        return result;
    }

    /**
     * 获取序列
     *
     * @param length            长度
     * @param flag              标识
     * @param dateTimeFormatter 日期格式
     * @return string
     */
    private static String getSeq(double length, boolean flag, DateTimeFormatter dateTimeFormatter) {
        final int ten = 10;
        DateTime dateTime = new DateTime();
        String result = dateTime.toString(dateTimeFormatter).trim();
        int random = new Random().nextInt((int) Math.pow((double) ten, length));
        result = result.concat(String.valueOf(random));
        for (String item : sequenceSet) {
            if (item.equals(result)) {
                flag = false;
            }
        }
        if (sequenceSet.size() == NumberDict.BYTE_NUM) {
            sequenceSet.clear();
        }
        if (flag) {
            sequenceSet.add(result);
            LOCK.decrementAndGet();
        } else {
            LOCK.decrementAndGet();
            generateSequence(length);
        }
        return result;
    }
}
